package org.easyexcel.Test;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

public class TheardOrdey {

    public static void main(String[] args) {
        Object o = new Object();
        AtomicBoolean ist2first = new AtomicBoolean(false);
        Thread t1 = new Thread(() -> {
            synchronized (o) {
                while (!ist2first.get()) {
                    try {
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("t1");
            }

        }, "t1");

        Thread t2 = new Thread(() -> {
            synchronized (o) {
                System.out.println("t2");
                ist2first.set(true);
                o.notify();
            }

        }, "t2");
        t1.start();
        t2.start();
    }
}

class MyRenntLock1 {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        AtomicBoolean ist2first = new AtomicBoolean(false);


        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                if (!ist2first.get()) {
                    condition.await();
                }
                System.out.println("t1");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }


        });

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("t2");
                ist2first.compareAndSet(false, true);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        t1.start();
        t2.start();
    }

}

class MyRenntLock2 {

    public static void main(String[] args) {

        Thread t1 = new Thread(() -> {
            LockSupport.park();
            System.out.println("t1");
        }, "t1");

        Thread t2 = new Thread(() -> {
            System.out.println("t2");
            LockSupport.unpark(t1);
        }, "t2");
        t1.start();
        t2.start();
    }

}

class MyRenntLock3 {
    public static void main(String[] args) {
        MyRenntLock3 myRenntLock3 = new MyRenntLock3(5, 1);
        new Thread(() -> myRenntLock3.print("A", 1, 2)).start();
        new Thread(() -> myRenntLock3.print("B", 2, 3)).start();
        new Thread(() -> myRenntLock3.print("C", 3, 1)).start();
    }

    private int flag;
    private int loopNum;

    public MyRenntLock3(int loopNum, int flag) {
        this.loopNum = loopNum;
        this.flag = flag;
    }

    private void print(String context, int waitflag, int nextFlag) {
        synchronized (this) {
            for (int i = 0; i < loopNum; i++) {
                while (flag != waitflag) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(context);
                flag = nextFlag;
                this.notifyAll();
            }
        }
    }
}

class MyRenntLock4 extends ReentrantLock {
    private int loopNum;
    private MyRenntLock4(int loopNum) {
        this.loopNum = loopNum;
    }
    public static void main(String[] args) {
        MyRenntLock4 myRenntLock4 = new MyRenntLock4(5);
        Condition a = myRenntLock4.newCondition();
        Condition b = myRenntLock4.newCondition();
        Condition c = myRenntLock4.newCondition();
        new Thread(() -> {myRenntLock4.print("A", a, b);}).start();
        new Thread(() -> {myRenntLock4.print("B", b, c);}).start();
        new Thread(() -> {myRenntLock4.print("C", c, a);}).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        myRenntLock4.lock();
        try {
            System.out.println("开始.....");
            a.signal();
        } finally {
            myRenntLock4.unlock();
        }
    }

    private void print(String context, Condition CurrentRom, Condition nextRom) {
        for (int i = 0; i < loopNum; i++) {
            lock();
            try {
                CurrentRom.await();
                System.out.println(context);
                nextRom.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                unlock();
            }
        }
    }
}

class ParkUnpark {
    private int loopNum;
    static Thread t1;
    static Thread t2;
    static Thread t3;
    private ParkUnpark(int loopNum) {
        this.loopNum = loopNum;
    }

    public static void main(String[] args) {
        ParkUnpark pu = new ParkUnpark(5);
        t1 = new Thread(() -> pu.print("t1", t2));
        t2 = new Thread(() -> pu.print("t2", t3));
        t3 = new Thread(() -> pu.print("t3", t1));
        t1.start();
        t2.start();
        t3.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        LockSupport.unpark(t1);
    }
    private void print(String context, Thread next) {
       for (int i = 0; i < loopNum; i++){
           LockSupport.park();
           System.out.println(context);
           LockSupport.unpark(next);
       }
    }
}

